home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 20
/
Cream of the Crop 20 (Terry Blount) (1996).iso
/
os2
/
sysb091a.zip
/
sysbench
/
src
/
pmb_fft.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-05
|
12KB
|
573 lines
/*
C Program: Test_Fast_Fourier_Transform_in_Double_Precision (TFFTDP.c)
by: Dave Edelblute, edelblut@cod.nosc.mil, 05 Jan 1993
*/
//#include <stdio.h>
#include <math.h>
/***************************************************************/
/* Timer options. You MUST uncomment one of the options below */
/* or compile, for example, with the '-DUNIX' option. */
/* */
/* Example compilation: */
/* UNIX systems: */
/* cc -DUNIX -O tfftdp.c -o fft -lm */
/***************************************************************/
/* #define Amiga */
/* #define UNIX */
/* #define UNIX_Old */
/* #define VMS */
/* #define BORLAND_C */
/* #define MSC */
/* #define MAC */
/* #define IPSC */
/* #define FORTRAN_SEC */
/* #define GTODay */
/* #define CTimer */
/* #define UXPM */
#ifndef PI
#define PI 3.14159265358979323846
#endif
static double xr[262144],xi[262144];
double pmb_fft()
{
int i,j,np,npm,lp,n2,kr,ki;
double *pxr,*pxi;
double a,enp,t,x,y,z,zr,zi,zm;
double t1,t2,t3,benchtime,VAX_REF,dtime();
int dfft();
np = 8;
pxr = xr;
pxi = xi;
// printf("\nFFT benchmark - Double Precision - V1.0 - 05 Jan 1993\n\n");
// printf("FFT size Time(sec) max error\n");
t3 = dtime();
for (lp = 1; lp <= 15; lp++ )
{
np = np * 2;
// printf(" %7d ",np);
enp = np;
npm = np / 2 - 1;
t = PI / enp;
*pxr = (enp - 1.0) * 0.5;
*pxi = 0.0;
n2 = np / 2;
*(pxr+n2) = -0.5;
*(pxi+n2) = 0.0;
for (i = 1; i <= npm; i++)
{
j = np - i;
*(pxr+i) = -0.5;
*(pxr+j) = -0.5;
z = t * (double)i;
y = -0.5*(cos(z)/sin(z));
*(pxi+i) = y;
*(pxi+j) = -y;
}
t1 = dtime();
dfft(xr,xi,np);
t2 = dtime() - t1;
if (t2 < 0.0) t2 = 0.0;
// printf(" %10.4lf ",t2);
/*
for (i=0; i<=15; i++) printf("%d %g %g\n",i,xr[i],xi[i]);
*/
zr = 0.0;
zi = 0.0;
kr = 0;
ki = 0;
npm = np-1;
for (i = 0; i <= npm; i++ )
{
a = fabs( xr[i] - i );
if (zr < a)
{
zr = a;
kr = i;
}
a = fabs(xi[i]);
if (zi < a)
{
zi = a;
ki = i;
}
}
zm = zr;
if ( fabs(zr) < fabs(zi) ) zm = zi;
// printf(" %10.2g %10.4\n",zm,t2);
/*
printf("re %7d %10.2g im %7d %10.2g\n",kr,zr,ki,zi);
*/
}
benchtime = dtime() - t3;
VAX_REF = 140.658;
// printf("\nBenchTime (sec) = %10.4lf\n",benchtime);
// printf("VAX_FFTs = %10.3lf\n\n",VAX_REF/benchtime);
return VAX_REF/benchtime;
}
/********************************************************/
/* A Duhamel-Hollman split-radix dif fft */
/* Ref: Electronics Letters, Jan. 5, 1984 */
/* Complex input and output data in arrays x and y */
/* Length is n. */
/********************************************************/
static int dfft( x, y, np )
double x[]; double y[]; int np ;
{
double *px,*py;
int i,j,k,m,n,i0,i1,i2,i3,is,id,n1,n2,n4;
double a,e,a3,cc1,ss1,cc3,ss3,r1,r2,s1,s2,s3,xt,tpi;
px = x - 1;
py = y - 1;
i = 2;
m = 1;
while (i < np)
{
i = i+i;
m = m+1;
}
n = i;
if (n != np)
{
for (i = np+1; i <= n; i++)
{
*(px + i) = 0.0;
*(py + i) = 0.0;
}
printf("nuse %d point fft",n);
}
n2 = n+n;
tpi = 2.0 * PI;
for (k = 1; k <= m-1; k++ )
{
n2 = n2 / 2;
n4 = n2 / 4;
e = tpi / (double)n2;
a = 0.0;
for (j = 1; j<= n4 ; j++)
{
a3 = 3.0 * a;
cc1 = cos(a);
ss1 = sin(a);
cc3 = cos(a3);
ss3 = sin(a3);
a = e * (double)j;
is = j;
id = 2 * n2;
while ( is < n )
{
for (i0 = is; i0 <= n-1; i0 = i0 + id)
{
i1 = i0 + n4;
i2 = i1 + n4;
i3 = i2 + n4;
r1 = *(px+i0) - *(px+i2);
*(px+i0) = *(px+i0) + *(px+i2);
r2 = *(px+i1) - *(px+i3);
*(px+i1) = *(px+i1) + *(px+i3);
s1 = *(py+i0) - *(py+i2);
*(py+i0) = *(py+i0) + *(py+i2);
s2 = *(py+i1) - *(py+i3);
*(py+i1) = *(py+i1) + *(py+i3);
s3 = r1 - s2; r1 = r1 + s2;
s2 = r2 - s1; r2 = r2 + s1;
*(px+i2) = r1*cc1 - s2*ss1;
*(py+i2) = -s2*cc1 - r1*ss1;
*(px+i3) = s3*cc3 + r2*ss3;
*(py+i3) = r2*cc3 - s3*ss3;
}
is = 2 * id - n2 + j;
id = 4 * id;
}
}
}
/************************************/
/* Last stage, length=2 butterfly */
/************************************/
is = 1;
id = 4;
while ( is < n)
{
for (i0 = is; i0 <= n; i0 = i0 + id)
{
i1 = i0 + 1;
r1 = *(px+i0);
*(px+i0) = r1 + *(px+i1);
*(px+i1) = r1 - *(px+i1);
r1 = *(py+i0);
*(py+i0) = r1 + *(py+i1);
*(py+i1) = r1 - *(py+i1);
}
is = 2*id - 1;
id = 4 * id;
}
/*************************/
/* Bit reverse counter */
/*************************/
j = 1;
n1 = n - 1;
for (i = 1; i <= n1; i++)
{
if (i < j)
{
xt = *(px+j);
*(px+j) = *(px+i);
*(px+i) = xt;
xt = *(py+j);
*(py+j) = *(py+i);
*(py+i) = xt;
}
k = n / 2;
while (k < j)
{
j = j - k;
k = k / 2;
}
j = j + k;
}
/*
for (i = 1; i<=16; i++) printf("%d %g %gn",i,*(px+i),(py+i));
*/
return(n);
}
/*****************************************************/
/* Various timer routines. */
/* Al Aburto, aburto@marlin.nosc.mil, 20 Dec 1992 */
/* */
/* t = dtime() outputs the current time in seconds. */
/* Use CAUTION as some of these routines will mess */
/* up when timing across the hour mark!!! */
/* */
/* For timing I use the 'user' time whenever */
/* possible. Using 'user+sys' time is a separate */
/* issue. */
/* */
/* Example Usage: */
/* [timer options added here] */
/* main() */
/* { */
/* double starttime,benchtime,dtime(); */
/* */
/* starttime = dtime(); */
/* [routine to time] */
/* benchtime = dtime() - starttime; */
/* } */
/* */
/* [timer code below added here] */
/*****************************************************/
/*********************************/
/* Timer code. */
/*********************************/
/*******************/
/* Amiga dtime() */
/*******************/
#ifdef Amiga
#include <ctype.h>
#define HZ 50
double dtime()
{
double q;
struct tt {
long days;
long minutes;
long ticks;
} tt;
DateStamp(&tt);
q = ((double)(tt.ticks + (tt.minutes * 60L * 50L))) / (double)HZ;
return q;
}
#endif
/*****************************************************/
/* UNIX dtime(). This is the preferred UNIX timer. */
/* Provided by: Markku Kolkka, mk59200@cc.tut.fi */
/* HP-UX Addition by: Bo Thide', bt@irfu.se */
/*****************************************************/
#ifdef UNIX
#include <sys/time.h>
#include <sys/resource.h>
#ifdef __hpux
#include <sys/syscall.h>
#define getrusage(a,b) syscall(SYS_getrusage,a,b)
#endif
struct rusage rusage;
double dtime()
{
double q;
getrusage(RUSAGE_SELF,&rusage);
q = (double)(rusage.ru_utime.tv_sec);
q = q + (double)(rusage.ru_utime.tv_usec) * 1.0e-06;
return q;
}
#endif
/***************************************************/
/* UNIX_Old dtime(). This is the old UNIX timer. */
/* Use only if absol